package cate.game.pvp.championrace.data;

import cate.common.table.d.GDFight;
import cate.game.framework.common.compress.PlaySideCompressHelper;
import cate.game.play.part.PlaySide;
import cate.game.role.RoleSnapshot;
import cate.game.util.GameKit;
import easy.java.practice.errorcode.EcResult;
import lombok.Data;
import lombok.ToString;
import org.springframework.data.annotation.Id;

import java.util.Objects;

@ToString
@Data
public class ChampionRaceBetRecord {
    public static final String INDEX_NAME = "INDEX";

    @Id
    private String uid = GameKit.uid();

    private ChampionRaceSpec spec;

    private RoleSnapshot snapshotA;
    private RoleSnapshot snapshotB;

    private byte winner;

    private long aCoinTotal;
    private long bCoinTotal;
    private int sA;
    private float sxA;
    private int sB;
    private float sxB;

    private long pA;
    private long pB;

    private float pxA;
    private float pxB;
    private float prePxA;
    private float prePxB;

    public static ChampionRaceBetRecord of(ChampionRaceRecord record, ChampionRacePs psA, ChampionRacePs psB, byte winner) {
        ChampionRaceBetRecord betRd = new ChampionRaceBetRecord();
        ChampionRaceSpec spec = ChampionRaceSpec.of(
                record.getSpec().getSeason(),
                record.getSpec().getPeriod(),
                (byte) 0,
                record.getSpec().getRound()
        );
        betRd.setSpec(spec);
        long pA = 0L;
        if (Objects.nonNull(psA)) {
            EcResult<PlaySide> r = PlaySideCompressHelper.uncompressEc(psA.getCpsList().getLast());
            if (r.ok() && Objects.nonNull(r.data)) {
                pA = r.data.getTotalPower();
                betRd.setSnapshotA(r.data.snapshot);
            }
        }
        betRd.setPA(pA);

        long pB = 0L;
        if (Objects.nonNull(psB)) {
            EcResult<PlaySide> r = PlaySideCompressHelper.uncompressEc(psB.getCpsList().getLast());
            if (r.ok() && Objects.nonNull(r.data)) {
                pB = r.data.getTotalPower();
                betRd.setSnapshotB(r.data.snapshot);
            }
        }
        betRd.setPB(pB);
        betRd.setPxA(betRd.calPx(pB, 0L));
        betRd.setPxB(betRd.calPx(pA, 0L));
        betRd.setWinner(winner);
        betRd.setPrePxA(betRd.getPxA());
        betRd.setPrePxB(betRd.getPrePxB());
        return betRd;
    }

    public void update(byte side, long coins) {
        if (side == GDFight.Team.A) {
            sA++;
            aCoinTotal += coins;
        } else if (side == GDFight.Team.B) {
            sB++;
            bCoinTotal += coins;
        }
        sxA = ((float) sA / (sA + sB));
        sxB = ((float) sB / (sA + sB));
        prePxA = pxA;
        prePxB = pxB;
        pxB = calPx(pA, aCoinTotal);
        pxA = calPx(pB, bCoinTotal);
    }

    private float calPx(float power, long coins) {
        float px = ((power / (pA + pB)) + ((float) coins / (aCoinTotal + bCoinTotal + 1))) / 2;
        return Math.max(0.01f, px) + 1;
    }
}
